package h5

import (
	"chess_platform/controllers"
	"chess_platform/internal/alisdk"
	. "chess_platform/internal/common"
	"chess_platform/internal/token"
	"chess_platform/models/h5"
	"fmt"
	"time"
)

//[h5]代理开通流程
type AgentController struct {
	GrantController
}

func (b *AgentController) Prepare() {
	LogH5.Debug("用户输入:" + string(b.Ctx.Input.RequestBody))
	LogH5.Debug("用户访问url:" + b.Ctx.Input.URL())
	b.Res = new(controllers.Response)
	var t controllers.Token
	err := b.Unmarshal(&t)
	if err != nil {
		b.DecodeParamsError(err)
		return
	}
	ex, err := token.Parse(t.Token)
	if err != nil || ex.GetTokenType() != TokenH5 {
		LogH5.Error("token解析:" + err.Error())
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserUnauthorized
		b.Response()
		return
	}
	if ex.IsExpire() {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserExpire
		b.Response()
		return
	}
	b.Uid = ex.GetId()

	keyAccessLimit := fmt.Sprintf("H5UserLimit-%v", b.Uid)
	if !AccessLimit(keyAccessLimit, Al.Frequency, Al.ExpireTime) {
		b.ResponseFail("操作过于频繁，请稍候再操作")
		return
	}

	b.Level = ex.GetLevel()
	status, _ := ex.GetInfo().(float64)

	b.Status = int64(status)
	if b.Status == FirstTopUpSuccess {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgUserNotPass
		b.Response()
		return
	}
	field := []string{"status", "pid", "create_time"}
	u, err := h5.SpecifyUserInfoById(b.Uid, field)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if u == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrUserNotFound
		b.Response()
		return
	}

	b.Status = u.Status
	LogH5.Debug("用户Uid:%d", b.Uid)
	LogH5.Debug("用户Level:%d", b.Level)
	LogH5.Debug("用户Status:%d", b.Status)

	//如果代理仅仅是注册成功了或审核为拒绝，但是一直没输入授权码，那么就更新注册时间为现在,当作没有超过24小时
	//判断此次申请是否已经超过24小时，一级代理都没有处理,就自动变成拒绝
	//拒绝之后,要修改用户状态,并且要还一个名额给一级代理
	if b.Ctx.Input.URL() == "/v1/h5/user/self-info" {
		return
	}
	ok, err := h5.HandleAgentStatus(u.CreateTime, b.Uid, u.Pid,
		u.Status == RegisterSuccess || u.Status == VerifyNotPass)

	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if !ok {
		b.ResponseFail("您的申请长时间未充值激活,自动拒绝")
		return
	}

}

func (b *AgentController) URLMapping() {
	b.Mapping("TopUp", b.TopUp)
	b.Mapping("InitialBuyCard", b.InitialBuyCard)
	b.Mapping("BindPhone", b.BindPhone)
	b.Mapping("SelfInfo", b.SelfInfo)
	b.Mapping("AuthCode", b.AuthCode)
	b.Mapping("AgentInfo", b.AgentInfo)

}

// @Title 第一次充值(显示价格)
// @Description 第一次充值(显示价格)
// @Success 0
// @router /top-up [post]
func (b *AgentController) TopUp() {
	if b.Status != VerifyPass {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserForbidden
		b.Response()
		return
	}
	/*
		field := []string{"pid", "create_time"}
		u, err := h5.SpecifyUserInfoById(b.Uid, field)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if u == nil {
			b.Res.Code = ErrNotFound
			b.Res.Msg = MsgErrUserNotFound
			b.Response()
			return
		}
	*/

	//根据b.Level来获取应该充值哪一个
	tu, err := h5.TopUpByLevel(b.Level)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = tu
	b.ResponseSuccess()
}

// @Title 第一次充值(爱贝支付)
// @Description 第一次充值(爱贝支付)
// @Param   pay_type       body    int true      "支付类型,2-微信支付,3-支付宝支付"
// @Param   url_r          body    int true      "支付成功回调url"
// @Param   url_h          body    int true      "支付取消回调url"
// @Success 0
// @router /initial-buy-card [post]
func (b *AgentController) InitialBuyCard() {
	if b.Status != VerifyPass {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserForbidden
		b.Response()
		return
	}
	/*
		field := []string{"pid", "create_time"}
		u, err := h5.SpecifyUserInfoById(b.Uid, field)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if u == nil {
			b.Res.Code = ErrNotFound
			b.Res.Msg = MsgErrUserNotFound
			b.Response()
			return
		}
		//判断此次申请是否已经超过24小时，一级代理都没有处理,就自动变成拒绝
		//拒绝之后,要修改用户状态,并且要还一个名额给一级代理
		ok, err := h5.HandleAgentStatus(u.CreateTime, b.Uid, u.Pid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if !ok {
			b.ResponseFail("您的申请长时间未充值激活,自动拒绝")
			return
		}
	*/

	type Params struct {
		PayType int64  `json:"pay_type" valid:"Range(2,3)"`
		UrlR    string `json:"url_r" valid:"Required"`
		UrlH    string `json:"url_h" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	//根据b.Level来获取应该充值哪一个
	tu, err := h5.TopUpByLevel(b.Level)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	order := map[string]interface{}{
		"uid":        b.Uid, //代理id
		"user_type":  Agent,
		"pay_type":   p.PayType,
		"order_type": OrderDiamond,
		"amount":     tu.Amount,
		"card_num":   tu.CardNum,
		"status":     OrderNotPay,
		"is_first":   FirstTimeBuyCard,
		"order_time": time.Now().Unix(),
	}
	orderId, err := h5.PreOrderPay(order)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	notifyUrl := BasePayCallBack + "/v1/h5/ipay-callback"
	orderIdStr := fmt.Sprintf("%v%v", H5IPayPre, orderId)
	price := float32(tu.Amount) / 100 //我们数据库存在的整型,单位是分,所以要除以100转为元
	transId, err := H5IPay.CreateIpayOrder(1, "", orderIdStr, price, "xiashen", "", notifyUrl)
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	updateData := map[string]interface{}{
		"transaction_id": transId,
	}
	_, err = h5.UpdateOrder(updateData, orderId)
	if err != nil {
		LogH5.Error(fmt.Sprintf("写入爱贝的订单号失败:%v", err.Error()))
	}
	payUrl, err := H5IPay.GetHtml5PayUrl(transId, p.UrlR, p.UrlH, IPayPayType(p.PayType))
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	b.Res.Data = payUrl
	b.ResponseSuccess()
}

// @Title 绑定手机号
// @Description 绑定手机号
// @Param   phone     body    string  true      "手机号"
// @Param   password  body    string  true      "密码"
// @Param   captcha   body    string  true      "短信验证码"
// @Success 0 {string} 状态码
// @Failure 399
// @router /bind-phone [post]
func (b *AgentController) BindPhone() {
	if b.Status != AuthCodeSuccess {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserForbidden
		b.Response()
		return
	}

	type Params struct {
		Phone    string
		Password string
		Captcha  string
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}

	b.Valid.Required(p.Phone, "phone").Message("手机号不能为空")
	b.Valid.Phone(p.Phone, "phone").Message("错误的手机号")
	b.Valid.MinSize(p.Password, 6, "password").Message("密码长度为6-15个字符")
	b.Valid.MaxSize(p.Password, 15, "password").Message("密码长度为6-15个字符")
	b.Valid.Required(p.Captcha, "captcha").Message("验证码不能为空")
	b.Valid.Numeric(p.Captcha, "captcha").Message("验证码为6位数字")
	b.Valid.Length(p.Captcha, 6, "captcha").Message("验证码为6位数字")
	if !b.VerifyParamsError() {
		return
	}
	err, ok := alisdk.VerifySMSCaptcha(p.Phone, p.Captcha, KeyH5Phone, MemCache)
	if !ok {
		b.Res.Code = ErrCaptchaVerify
		b.Res.Msg = err.Error()
		b.Response()
		LogH5.Notice(err.Error())
		return
	}

	uid, err := h5.IsUserExistByPhone(p.Phone)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if uid != 0 {
		b.Res.Code = ErrAlreadyExist
		b.Res.Msg = MsgErrPhoneAlreadyExist
		b.Response()
		return
	}
	status := BindPhoneSuccess
	user := map[string]interface{}{
		"phone":       p.Phone,
		"password":    Md5sum(p.Password),
		"status":      status,
		"create_time": time.Now().Unix(),
	}
	if b.Level != Level1 { //[需求变更]取消审核，直接跳到审核通过
		status = VerifyPass
		user["status"] = status
	}

	_, err = h5.UpdateUser(user, b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = map[string]interface{}{
		"status": status,
		"level":  b.Level,
	}
	b.ResponseSuccess()
}

// @Title 获取自己用户信息
// @Description 获取自己用户信息,在代理未成功正式代理时使用
// @Success 0 {object} h5.User
// @router /self-info [post]
func (b *AgentController) SelfInfo() {
	field := []string{"uid", "nickname", "head_img_url", "status", "level"}
	dbUser, err := h5.SpecifyUserInfoById(b.Uid, field)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if dbUser == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrUserNotFound
		b.Response()
		return
	}
	data := map[string]interface{}{
		"uid":          dbUser.Uid,
		"nickname":     dbUser.Nickname,
		"head_img_url": dbUser.HeadImgUrl,
		"status":       dbUser.Status,
		"level":        dbUser.Level,
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 输入授权码
// @Description 输入授权码
// @Param   auth_code body    string  true      "授权码"
// @Success 0 {string} 生成新的token
// @Failure 399
// @router /auth-code [post]
func (b *AgentController) AuthCode() {
	if b.Status != RegisterSuccess && b.Status != VerifyNotPass {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserForbidden
		b.Response()
		return
	}
	type Params struct {
		AuthCode string `json:"auth_code"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}

	b.Valid.Numeric(p.AuthCode, "auth_code").Message("授权码为纯数字")
	b.Valid.Length(p.AuthCode, 8, "auth_code").Message("授权码为8位数字")
	if !b.VerifyParamsError() {
		return
	}

	ac, err := h5.IsAuthCodeExist(p.AuthCode)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	//授权码不存在
	if ac.AuthCode == "" {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrAuthCodeNotFound
		b.Response()
		return
	}

	var GroupId int64 //一级代理所属的大区

	o := NewDBOrm(DBChessCenter)
	o.Begin()
	defer o.Rollback()
	//下面的应该有并发问题
	//如果开通二级代理,需要判断一级代理是否足够的名额,归属于同一级代理同一个大区
	if ac.Level == Level2 { //此授权码是用来自一级代理
		//获取一级代理的名额
		field := []string{"agent_num", "group_id"}
		u, err := h5.SpecifyUserInfoById(ac.Uid, field, o)
		if err != nil {
			o.Rollback()
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if u == nil {
			o.Rollback()
			LogH5.Error(b.SystemError(fmt.Sprintf("h5_user表里没有找到一级代理:%d,而h5_auth_code表里有", ac.Uid)))
			return
		}
		//代理名额不足
		if u.AgentNum < 1 {
			o.Rollback()
			b.Res.Code = ErrAgentNumNotEnough
			b.Res.Msg = MsgErrAgentNumNotEnough
			b.Response()
			return
		}
		//减少代理的名额
		n, err := h5.UpdateUserAgentNum(-1, ac.Uid, o)
		if err != nil || n == 0 {
			o.Rollback()
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		GroupId = u.GroupId
	}
	//查找自己的phone
	field := []string{"phone"}
	u, err := h5.SpecifyUserInfoById(b.Uid, field)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	status := AuthCodeSuccess
	user := map[string]interface{}{
		"status":   status,
		"level":    ac.Level,
		"pid":      ac.Uid, //一级代理或系统帐号的uid
		"group_id": GroupId,
	}

	if u != nil && u.Phone != "" { //判断此代理是否之前已经绑定过手机,比如说以前被拒绝了,手机号存在数据库里
		status = BindPhoneSuccess
		if b.Level == Level2 {
			status = VerifyPass //[需求变动]二级代理取消审核直接跳过审核
		}
		user["create_time"] = time.Now().Unix() //之前的注册时间改为现在
		user["status"] = status
	}

	_, err = h5.UpdateUser(user, b.Uid, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	data := map[string]interface{}{ //返回给前端的信息
		"level":  ac.Level,
		"status": status,
	}
	b.Res.Data = data
	b.Res.Token = token.Create(b.Uid, ac.Level, TokenH5, status)

	o.Commit()
	b.ResponseSuccess()
}

// @Title 输入授权码获得上级代理用户信息
// @Description 输入授权码获得上级代理用户信息
// @Param   auth_code body    string  false      "授权码,已经输入授权码就不用输入"
// @Success 0 {object} h5.User
// @Failure 399
// @router /agent-info [post]
func (b *AgentController) AgentInfo() {
	type Params struct {
		AuthCode string `json:"auth_code"`
	}
	var (
		p   Params
		uid int64
	)
	if !b.DecodeParams(&p) {
		return
	}

	if p.AuthCode != "" { //授权码不为空时，是第一次输入
		b.Valid.Numeric(p.AuthCode, "auth_code").Message("授权码为纯数字")
		b.Valid.Length(p.AuthCode, 8, "auth_code").Message("授权码为8位数字")
		if !b.VerifyParamsError() {
			return
		}
		ac, err := h5.IsAuthCodeExist(p.AuthCode)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if ac.AuthCode == "" {
			b.Res.Code = ErrNotFound
			b.Res.Msg = MsgErrAuthCodeNotFound
			b.Response()
			return
		}
		uid = ac.Uid
	} else { //已经输入过授权码
		field := []string{"pid", "create_time"}
		u, err := h5.SpecifyUserInfoById(b.Uid, field)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if u == nil {
			b.Res.Code = ErrNotFound
			b.Res.Msg = MsgErrUserNotFound
			b.Response()
			return
		}
		/*
			//判断此次申请是否已经超过48小时，一级代理都没有处理,就自动变成拒绝
			//拒绝之后,要修改用户状态,并且要还一个名额给一级代理
			ok, err := h5.HandleAgentStatus(u.CreateTime, b.Uid, u.Pid)
			if err != nil {
				LogH5.Error(b.DatabaseError(err.Error()))
				return
			}
			if !ok {
				b.ResponseFail("您的申请长时间未被审核,自动拒绝")
				return
			}
		*/
		uid = u.Pid
	}
	field := []string{"nickname", "head_img_url", "phone", "level"}
	u, err := h5.SpecifyUserInfoById(uid, field)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if u == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrUserNotFound
		b.Response()
		return
	}

	data := map[string]interface{}{
		"nickname":     u.Nickname,
		"head_img_url": u.HeadImgUrl,
		"phone":        u.Phone,
		"level":        u.Level,
	}

	b.Res.Data = data
	b.ResponseSuccess()
}
